/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.duktape.octane.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.PopupDialog;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.Entry;
import ohos.global.resource.RawFileEntry;
import ohos.global.resource.ResourceManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import com.example.duktape.octane.Engine;
import com.example.duktape.octane.ResourceTable;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * duktape Demo 的MainAbilitySlice
 *
 * @since 2021-03-24
 */
public class MainAbilitySlice extends AbilitySlice {
    private static final int CASE_1 = 1;
    private static final int CASE_2 = 2;
    private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");
    private static final String FILEPATH = "resources/rawfile/";
    private static final String DUKTAPE = "Duktape";
    private static final int SPACE_WIDTH = 400;
    private static final int SPACE_HIGH = 300;
    private static final int SPACE_Y = 295;
    Button btn1;
    Button btn2;
    Text content;

    private ResourceManager resourceManager;
    private MyEventHandler myHandler;

    private int eventId1 = CASE_1;
    private int eventId2 = CASE_2;
    private long param = 0L;
    private Object object;
    private InnerEvent event1;
    private ShapeElement ele2;

    private PopupDialog popupDialog;
    private Text styl1;
    private Text styl2;

    private String style = DUKTAPE;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        btn1 = (Button) findComponentById(ResourceTable.Id_btn1);
        btn2 = (Button) findComponentById(ResourceTable.Id_btn2);
        content = (Text) findComponentById(ResourceTable.Id_context);

        ele2 = new ShapeElement();
        ele2.setRgbColor(RgbColor.fromArgbInt(Color.LTGRAY.getValue()));
        btn2.setBackground(ele2);

        resourceManager = this.getResourceManager();

        myHandler = new MyEventHandler(EventRunner.getMainEventRunner());

        initEvent();
    }

    private void initEvent() {
        btn1.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                HiLog.info(TAG, "btn1 Click");

                showDialog(component);
            }
        });

        btn2.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                HiLog.info(TAG, "btn2 Click");
                ShapeElement ele = new ShapeElement();
                ele.setRgbColor(RgbColor.fromArgbInt(Color.WHITE.getValue()));
                btn1.setClickable(false);
                btn2.setClickable(false);
                btn2.setBackground(ele);

                // 处理文件
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        HiLog.info(TAG, "线程进来了");
                        Engine engine;
                        if (DUKTAPE.equals(style)) {
                            engine = Engine.values()[0];
                        } else {
                            engine = Engine.values()[1];
                        }

                        Closeable instance = engine.create();
                        String str = getFile(DUKTAPE.equals(style), engine, instance);
                        String results = (String) engine.evaluate(instance, "getResults();", "?");
                        HiLog.info(TAG, "sync task1 run results :" + results);
                        StringBuilder sbJs = new StringBuilder();
                        object = sbJs.append(str).append(System.lineSeparator()).append(results).toString();
                        event1 = InnerEvent.get(eventId1, param, object);
                        myHandler.sendEvent(event1);
                        myHandler.sendEvent(InnerEvent.get(eventId2, param, null));
                        btn1.setClickable(true);
                        btn2.setClickable(true);
                    }
                }).start();
            }
        });
    }

    /**
     * 引擎style dialog选择
     *
     * @param component dialog 显示在那个控制附近
     */
    public void showDialog(Component component) {
        if (popupDialog == null) {
            popupDialog = new PopupDialog(MainAbilitySlice.this, component, SPACE_WIDTH, SPACE_HIGH);
        }
        DirectionalLayout layout = (DirectionalLayout) LayoutScatter.getInstance(this)
            .parse(ResourceTable.Layout_dialog_style, null, false);
        popupDialog.setCustomComponent(layout);
        HiLog.info(TAG, "showDialog");
        styl1 = (Text) layout.findComponentById(ResourceTable.Id_type1);
        styl2 = (Text) layout.findComponentById(ResourceTable.Id_type2);

        styl1.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                HiLog.info(TAG, "选择了Duktape");
                btn1.setText(DUKTAPE);
                style = DUKTAPE;
                popupDialog.destroy();
            }
        });

        styl2.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                HiLog.info(TAG, "选择了QuickJS");
                btn1.setText("QuickJS");
                style = "QuickJS";
                popupDialog.destroy();
            }
        });
        popupDialog.setTransparent(true);
        popupDialog.setBackColor(Color.WHITE);
        popupDialog.setAutoClosable(true);
        popupDialog.showOnCertainPosition(LayoutAlignment.LEFT | LayoutAlignment.TOP, 0, SPACE_Y);
    }

    /**
     * 获取资源文件夹下面的文件
     *
     * @param isDuk 区分具体的引擎 true 是Duktape false是QuickJS
     * @param engine 引擎
     * @param instance 引擎具体的构造实现类
     * @return 拼接返回后的结果
     */
    public String getFile(Boolean isDuk, Engine engine, Closeable instance) {
        RawFileEntry rawFileEntry = resourceManager.getRawFileEntry(String.format(FILEPATH));
        StringBuilder sb = new StringBuilder();
        try {
            Entry[] entey = rawFileEntry.getEntries();
            HiLog.info(TAG, "entey length = " + entey.length);

            String path = FILEPATH + entey[0].getPath() + "/";
            RawFileEntry rfEntry = resourceManager.getRawFileEntry(String.format(path));
            Entry[] entrys = rfEntry.getEntries();
            HiLog.info(TAG, "entrys length = " + entrys.length);

            for (int i = 0; i < entrys.length; i++) {
                if (isDuk && entrys[i].getPath().contains("mandreel")) {
                    continue;
                }
                long startTime = System.currentTimeMillis();
                readFile(path + entrys[i].getPath(), engine, instance);
                sb.append("octance/" + entrys[i].getPath()).append(" eval… ").
                    append(System.currentTimeMillis() - startTime).append(" ms").append(System.lineSeparator());
                HiLog.info(TAG, "octance/" + entrys[i].getPath() + " eval…  "
                    + (System.currentTimeMillis() - startTime));

                object = sb.toString();
                event1 = InnerEvent.get(eventId1, param, object);
                myHandler.sendEvent(event1);
            }
            sb.append(entey[1].getPath()).append(" eval… ");
            object = sb.toString();
            event1 = InnerEvent.get(eventId1, param, object);
            myHandler.sendEvent(event1);
            long stratReadOct = System.currentTimeMillis();
            readFile(FILEPATH + entey[1].getPath(), engine, instance);
            sb.append(System.currentTimeMillis() - stratReadOct).append(" ms").append(System.lineSeparator());
            object = sb.toString();
            event1 = InnerEvent.get(eventId1, param, object);
            myHandler.sendEvent(event1);
        } catch (IOException e) {
            HiLog.info(TAG, "octane IOException = " + e.toString());
        }
        return sb.toString();
    }

    /**
     * 读文件夹下面的文件
     *
     * @param path 文件路径
     * @param engine 引擎
     * @param instance 引擎具体的构造实现类
     */
    public void readFile(String path, Engine engine, Closeable instance) {
        BufferedReader bufferedReader = null;
        StringBuilder stringBuilder = new StringBuilder();
        try {
            RawFileEntry rawFileEntry = resourceManager.getRawFileEntry(String.format(path));
            InputStream inputStream = rawFileEntry.openRawFile();
            HiLog.info(TAG, "file path = " + path);
            if (inputStream == null) {
                return;
            }

            bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));

            String tempString = null;
            while ((tempString = bufferedReader.readLine()) != null) {
                stringBuilder.append(tempString).append(System.lineSeparator());
            }
            bufferedReader.close();
            HiLog.info(TAG, "读取完成 ");

            engine.evaluate(instance, stringBuilder.toString(), String.format(path));
        } catch (IOException e) {
            HiLog.info(TAG, "Exception : exception = " + e.toString());
        } finally {
            HiLog.info(TAG, "finally ");
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    HiLog.info(TAG, "finally Error ");
                }
            }
        }
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    /**
     * 自定义一个handler用于线程之间用来切换
     *
     * @since 2021-03-24
     */
    private class MyEventHandler extends EventHandler {
        private MyEventHandler(EventRunner runner) {
            super(runner);
        }

        // 重写实现processEvent方法
        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            HiLog.info(TAG, "MyEventHandler 接收到了 ");
            if (event == null) {
                return;
            }
            int eventId = event.eventId;
            switch (eventId) {
                case CASE_1:
                    // 待执行的操作，由开发者定义
                    HiLog.info(TAG, "content 设置值 " + (String) event.object);
                    content.setText((String) event.object);
                    break;

                case CASE_2:
                    // 待执行的操作，由开发者定义
                    btn1.setClickable(true);
                    btn2.setClickable(true);
                    btn2.setBackground(ele2);
                    break;

                default:
                    break;
            }
        }
    }
}
